
/*
 *  Source name     : lab1_p1_asmprog.s
 *  Executable name : lab1_p1_asmprog
 *  Version         : 1.1
 *  Created date    : 9/18/03
 *  Last update     : 1/28/05
 *  Author          : Jason Fritts, Roger Chamberlain
 *  Description     : Basic template for GNU assembly programs
 * 
 *  Build using these commands:
 *    as --gstabs lab1_p1_asmprog.s -o lab1_p1_asmprog.o
 *    gcc -g -c input.c -o input.o
 *    gcc lab1_p1_asmprog.o input.o -o lab1_p1_asmprog
 */

.equiv MIN_ELEMENTS, 1
.equiv MAX_ELEMENTS, 1000000
.equiv BOUND_WORD, 65536

.text
.global main				/* program entry point */

main:
    pushl %ebp				/* Create stack frame */
    movl  %esp, %ebp 			/* ebp marks our place in the stack */

    pushl %ebx				/* Save ebx, edi, & esi */
    pushl %edi
    pushl %esi

    /* start program code */

    pushl $MAX_ELEMENTS		/* query user for # of elements to print */
    pushl $MIN_ELEMENTS
    call  get_number
    addl  $8, %esp
    movl  %eax, n(,1)

    movl  $0, i(,1)			/* initialize first two elements */
    leal  num_set(,1), %eax
    movl  $1, 0(%eax)
    incl  i(,1)
    movl  $2, 4(%eax)
    incl  i(,1)

    /* find remaining n-2 elements */

    movl  $3, %ebx			/* j = 3 */

    j_loop:
	movl  i(,1), %eax
	cmpl  n(,1), %eax		/* is i < n? */
	jae   exit_j_loop
	
	movl  $0, mark(,1)		/* mark = 0 */

	movl  $2, k(,1)			/* k = 2 */

	k_loop:
	    cmpl  %eax, k(,1)		/* is k < i? */
	    jae   exit_k_loop

	    movl  k(,1), %esi
	    shll  $2, %esi		/* mult i by 4 to index into num_set */
	    movl  num_set(%esi), %ecx	/* get num_set[k] */

	    cmpl  $BOUND_WORD, %ecx	/* is k < 65536? */
	    jae   exit_k_loop

	    movl  $0, %edx
	    movl  %ebx, %eax		/* copy j into eax for division */
	    divl  %ecx			/* rem is in edx */
	    
	    cmpl  $0, %edx		/* is rem == 0? */
	    jne   end_k_loop
	    movl  $1, mark(,1)		/* mark = 1 */
	    jmp   exit_k_loop

	end_k_loop:
	    addl  $1, k(,1)		/* k = k + 1 */
	    jmp   k_loop

	exit_k_loop:

	cmpl  $0, mark(,1)		/* is mark == 0? */
	jne   end_j_loop
	movl  i(,1), %esi
	shll  $2, %esi			/* mult i by 4 to index into num_set */
	movl  %ebx, num_set(%esi)	/* num_set[i] = j */
	incl  i(,1)			/* i = i + 1 */

    end_j_loop:

	addl  $2, %ebx			/* j = j + 2 */
	jmp   j_loop

    exit_j_loop:

    /* print out n elements of pattern */

    pushl n(,1)				/* print "Display X element..." */
    pushl $out_str
    call printf
    addl  $8, %esp

    movl  $0, %ecx			/* i = 0 */

    print_loop:
	cmpl  n(,1), %ecx		/* is i < n? */
	jae   exit_print_loop
	
	movl  %ecx, %esi
	shll  $2, %esi			/* mult i by 4 to index into num_set */

	pushl %ecx			/* save necessary registers before */
	pushl %esi			/*   a procedure call */

	pushl num_set(%esi)		/* print out value of i-th element */
	pushl $elem_str
	call  printf
	addl  $8, %esp

	popl  %esi			/* restore regs after a procedure */
	popl  %ecx			/*   call */

	addl  $1, %ecx			/* i = i + 1 */
	jmp  print_loop

    exit_print_loop:

    pushl $end_line			/* print end of line */
    call  printf
    addl  $4, %esp

    /* end program code */

    popl  %esi				/* Restore ebx, edi, & esi */
    popl  %edi
    popl  %ebx
    movl  %ebp, %esp			/* Destroy stack frame */
    popl  %ebp
    ret					/* Return control to Linux */


.section .rodata			/* read-only (e.g. string) data */

    out_str:
	.string "\nDisplaying %d elements of pattern:\n    "
    elem_str:
	.string "%d "
    end_line:
	.string "\n"

.section .data				/* initialized data */

    i:
	.int	0
    k:
	.int   0

.section .bss				/* uninitialized data */

	.comm n, 4
	.comm mark, 4
	.comm num_set, 4*MAX_ELEMENTS

